﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.ServiceModel;
using System.Windows;
using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MusicStore.WebService.Test.MusicStoreServiceReference;

namespace MusicStore.WebService.Test
{
	/// <summary>
	/// operational test, warning these tests make your database dirty
	/// 
	/// todo: add some test cleanup data
	/// </summary>
	[TestClass]
	public class Tests : TestBase
	{
		
		[TestMethod]
		public void ExceptionTest()
		{
			MusicStoreServiceClient service = new MusicStoreServiceClient("binary");
			service.ThrowExceptionCompleted += (sender, e) =>
			                                   	{
																Assert.IsNotNull(e.Error);
																Assert.IsInstanceOfType(e.Error, typeof(FaultException<FaultDetail>));
			                                   	};
			service.ThrowExceptionAsync();
		}

		[TestMethod]
		[Asynchronous]
		public void SaveAlbum()
		{
			MusicStoreServiceClient service = new MusicStoreServiceClient("binary");

			Album a = CreateTestAlbum(0);
			service.SaveCompleted += (sender, e) =>
												{
													Assert.IsNull(e.Error);
													EnqueueTestComplete();
												};
			service.SaveAsync(a);
		}

		[TestMethod]
		[Asynchronous]
		public void SaveAndReadAlbum()
		{
			MusicStoreServiceClient service = new MusicStoreServiceClient("binary");
			int savedId = 0;
			Album a = CreateTestAlbum(0);
			service.SaveCompleted += (sender, e) =>
			{
				Assert.IsNull(e.Error);
				savedId = e.Result;
			};
			EnqueueCallback(() => service.SaveAsync(a));
			EnqueueConditional(() => savedId > 0);
			// we can now read back the album
			service.GetAlbumCompleted += (sender, e) =>
													{
														Assert.IsNull(e.Error);
														Assert.IsNotNull(e.Result);
														Assert.AreEqual(a.Title, e.Result.Title);
														Assert.AreEqual(a.Tracks.Count, e.Result.Tracks.Count);
														EnqueueTestComplete();
													};
			EnqueueCallback(() => service.GetAlbumAsync(savedId));
		}

		[TestMethod]
		[Asynchronous]
		public void SaveAndUpdateAndReadAlbum()
		{
			MusicStoreServiceClient service = new MusicStoreServiceClient("binary");
			int savedId = 0;
			Album a = CreateTestAlbum(0);
			bool serviceResponded = false;
			service.SaveCompleted += (sender, e) =>
			{
				Assert.IsNull(e.Error);
				savedId = e.Result;
				serviceResponded = true;
			};
			EnqueueCallback(() =>
									{
										serviceResponded = false;
										service.SaveAsync(a);
									});
			EnqueueConditional(() => serviceResponded);
			// we can now read back the album
			service.GetAlbumCompleted += (sender, e) =>
			{
				Assert.IsNull(e.Error);
				Assert.IsNotNull(e.Result);
				Assert.AreEqual(a.Title, e.Result.Title);
				Assert.AreEqual(a.Tracks.Count, e.Result.Tracks.Count);
				serviceResponded = true;
			};
			EnqueueCallback(() =>
									{
										serviceResponded = false;
										service.GetAlbumAsync(savedId);
									});
			EnqueueConditional(() => serviceResponded);
			// update the album changind the description and the tracks, then read it again
			EnqueueCallback(() =>
									{
										a.Note = "Modified";
										a.Tracks.RemoveAt(0);
										serviceResponded = false;
										service.SaveAsync(a);
									});
			EnqueueConditional(() => serviceResponded);

			EnqueueCallback(() =>
									{
										service.GetAlbumCompleted += (sender, e) =>
										{
											// addictional tests over the previous ones
											Assert.AreEqual("Modified", e.Result.Note);
											EnqueueTestComplete();
										};
										service.GetAlbumAsync(savedId);
									});
		}

		[TestMethod]
		[Asynchronous]
		public void SaveAndDeleteAlbum()
		{
			MusicStoreServiceClient service = new MusicStoreServiceClient("binary");
			int savedId = 0;
			Album a = CreateTestAlbum(0);
			service.SaveCompleted += (sender, e) =>
												{
													Assert.IsNull(e.Error);
													savedId = e.Result;
												};
			EnqueueCallback(() => service.SaveAsync(a));
			EnqueueConditional(() => savedId > 0);
			// we can now read back the album
			bool deleted = false;
			service.DeleteCompleted += (sender, e) =>
													{
														Assert.IsNull(e.Error);
														deleted = true;
													};
			EnqueueCallback(() => service.DeleteAsync(savedId));
			// wait for the object to be deleted
			EnqueueConditional(() => deleted);
			// try to read the object again
			service.GetAlbumCompleted += (sender, e) =>
			{
				Assert.IsNull(e.Error);
				Assert.IsNull(e.Result);
				EnqueueTestComplete();
			};
			EnqueueCallback(() => service.GetAlbumAsync(savedId));
		}

		static List<Album> CreateTestAlbums()
		{
			List<Album> albums = new List<Album>();
			for (int i = 0; i < 10; i++)
			{
				Album a = CreateTestAlbum(i);
				albums.Add(a);
			}
			return albums;
		}

		[TestMethod]
		[Asynchronous]
		public void SaveAlbumsGetList()
		{
			MusicStoreServiceClient service = new MusicStoreServiceClient("binary");

			List<Album> lst = CreateTestAlbums();
			int savedcount = 0;
			service.SaveCompleted += (sender, e) =>
			{
				Assert.IsNull(e.Error);
				savedcount++;
			};
			lst.ForEach(a => EnqueueCallback(() => service.SaveAsync(a)));
			EnqueueConditional(() => savedcount == lst.Count);
			// get a list of data
			service.GetAlbumsCompleted += (sender, e) =>
														{
															Assert.IsNull(e.Error);
															Assert.IsNotNull(e.Result);
															Assert.IsTrue(e.Result.Count > 0);
															EnqueueTestComplete();
														};
			EnqueueCallback(service.GetAlbumsAsync);
		}

		private static Album CreateTestAlbum(int i)
		{
			Album a = new Album
							{
								Author = "Author" + i,
								Genre = "Rock",
								Label = "Label" + i,
								Note = "Note" + i,
								PublicationDate = DateTime.Now,
								Title = "Title" + i
							};
			for (int j = 0; j < 10; j++)
			{
				Track t = new Track
								{
									Number = j,
									Duration = "Duration" + j,
									Title = "Title" + j
								};
				a.Tracks.Add(t);
			}
			return a;
		}
	}
}